MySQL-5.7 Insert语句详解
1.语法
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)]
{VALUES | VALUE} (value_list) [, (value_list)] ...
[ON DUPLICATE KEY UPDATE assignment_list]
INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
SET assignment_list
[ON DUPLICATE KEY UPDATE assignment_list]
INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
[INTO] tbl_name
[PARTITION (partition_name [, partition_name] ...)]
[(col_name [, col_name] ...)]
SELECT ...
[ON DUPLICATE KEY UPDATE assignment_list]
value:
{expr | DEFAULT}
value_list:
value [, value] ...
assignment:
col_name = value
assignment_list:
assignment [, assignment] ...
2.三种常用语法示例
mysql> desc students;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| sid | int(11) | NO | PRI | NULL | auto_increment |
| sname | varchar(54) | YES | | NULL | |
| gender | varchar(12) | YES | | NULL | |
| dept_id | int(11) | NO | MUL | NULL | |
+---------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> select * from students;
+-----+-------+--------+---------+
| sid | sname | gender | dept_id |
+-----+-------+--------+---------+
| 1 | aaa | 1 | 2 |
| 2 | bbb | 2 | 2 |
| 3 | ccc | 3 | 2 |
+-----+-------+--------+---------+
3 rows in set (0.00 sec)
mysql> insert into students values(4,'aaaa',1,1);
Query OK, 1 row affected (0.04 sec)
mysql> insert into students set sid=5,sname='ddd',gender=2,dept_id=1;
Query OK, 1 row affected (0.03 sec)
mysql> insert into students select * from students_bak;
说明:
insert...values和insert...set两种语句都是将指定的数据插入到现成的表中,而insert....select语句是将另外表中的数据查出来并插入到现成的表中;
3.属性说明
1)Partition
代表可以将数据插入到指定的表分区中
2)Tbl_name
代表将数据插入到目标表
3)Col_name
代表要插入指定数据的目标列,如果是多列则用逗号隔开,如果目标表中的某些列没有在Insert语句中指定,则这些列会插入默认值,当然可以使用default显示指定插入默认值
4)LOW_PRIORITY
INSERT的执行被推迟到没有其他用户正在读取表。在这种情况下,用户必须等到插入语句完成后,如果表频繁使用,它可能花很长时间。这与INSERT DELAYED让用户马上继续正好相反。
LOW_PRIORITY和HIGH_PRIORITY仅在MyISAM,MEMORY和MERGE三种存储引擎下才生效。
5)IGNORE
表中任何复制一个现有PRIMARY或UNIQUE键的行被忽略并且不被插入。如果你不指定IGNORE,插入如果有任何复制现有关键值的行被放弃。
当违反主键和唯一键约束条件时不报错只产生警告信息,违反的行被丢弃,而不是整个语句回退;在数据类型转换有问题时也是如此。
6)DELAYED(5.7版本不再支持,语句不会报错,但会产生警告)
如果用户不能等到INSERT完成,它是很有用的。当你为日志登录使用MySQL时,而且你也周期性地运行花很长时间完成的SELECT语句,这是一个常见的问题。
当你使用INSERT DELAYED时,用户将马上准备好,并且当表不被任何其他的线程使用时,行将被插入。
另一个使用INSERT DELAYED的主要好处是从很多用户插入被捆绑在一起并且写进一个块。这比做很多单独的插入要来的快。
使用DELAYED时有一些限制:
- INSERT DELAYED仅适用于MyISAM, MEMORY和ARCHIVE表。对于MyISAM表,如果在数据文件的中间没有空闲的块,则支持同时采用SELECT和INSERT语句。在这些情况下,基本不需要对MyISAM使用INSERT DELAYED。
- INSERT DELAYED应该仅用于指定值清单的INSERT语句。服务器忽略用于INSERT DELAYED...SELECT语句的DELAYED和INSERT DELAYED...ON DUPLICATE UPDATE语句的DELAYED。
- 因为在行被插入前,语句立刻返回,所以您不能使用LAST_INSERT_ID()来获取AUTO_INCREMENT值。AUTO_INCREMENT值可能由语句生成。
- 对于SELECT语句,DELAYED行不可见,直到这些行确实被插入了为止。
- DELAYED在从属复制服务器中被忽略了,因为DELAYED不会在从属服务器中产生与主服务器不一样的数据。
7)ON DUPLICATE KEY UPDATE
如果您指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则执行旧行UPDATE。
当您使用ON DUPLICATE KEY UPDATE时,DELAYED选项被忽略。
--假设a,b为唯一索引,表table没有1,2这样的行是正常插入数据,冲突时,更新c列的值
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=3;
--或者是
INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=values(c);
--引用其他列更新冲突的行
INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6) ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
向一个已定义为NOT NULL的列中插入NULL。对于一个多行INSERT语句或INSERT INTO...SELECT语句,根据列数据的类型,列被设置为隐含的默认值。对于数字类型,默认值为0;对于字符串类型,默认值为空字符串('');对于日期和时间类型,默认值为“zero”值。
INSERT INTO...SELECT的ON DUPLICATE KEY UPDATE
insert into tbl_name1(a,b,c)
select col1,col2,col3 from tbl_name2
ON DUPLICATE KEY UPDATE c=values(c);
4.注意事项
1)Values中除了可以指定确定的数值之外,还可以使用表达式expr
INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2); 正确
INSERT INTO tbl_name (col1,col2) VALUES(col2*2,15); 错误
2)执行结果
Insert...values和Insert...select语句执行结果如下:
Records:100 Duplicates:0 Warnings:0
Records代表语句操作了多少行数据,但不一定是多少行被插入的数据,因为如果存在相同行数据且违反了某个唯一性,Duplicates会显示非0数值;
warnings代表语句执行过程中的一些警告信息;
Warnings的一些触发情况:
- 插入NULL到被声明了NOT NULL的列,列被设置为它的缺省值。
- 将超出列范围的值设置给一个数字列,值被剪切为范围内适当的端点值。
- 将数字列设成例如'10.34 a'的值,拖尾的垃圾被剥去并仍然是数字部分被插入。如果值根本不是一个数字,列被设置到0。
- 把一个字符串插入到超过列的最大长度的一个CHAR、VARCHAR、TEXT或BLOB列中。值被截断为列的最大长度。
- 把一个对列类型不合法的值插入到一个日期或时间列。列被设置为该列类型适当的“零”值。
3)Insert...select
当目标表和select语句中的表相同时,则会将select语句的结果存放在临时表中,再插入到目标表中(注意执行顺序)。
4)INSERT INTO ... SELECT语句满足下列条件
- 查询不能包含一个ORDER BY子句。
- INSERT语句的目的表不能出现在SELECT查询部分的FROM子句,因为这在ANSI SQL中被禁止让从你正在插入的表中SELECT。(问题是SELECT将可能发现在同一个运行期间内先前被插入的记录。当使用子选择子句时,情况能很容易混淆)
- AUTO_INCREMENT列像往常一样工作。